#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         Event.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the Event class, who's instances
#               represent a collection of end-user defined Actions
#               to handle specific Knowledge Engine object events.
#
# See Also:     GenericObject, EventDefinition, EventReflection
#               Action
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.GenericObject import GenericObject, GenericObjectInfo
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from Globals import Persistent
from ImageFile import ImageFile
from Products.ZSQLMethods.SQL import SQL

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## EventInfo Class Definition
class EventInfo(GenericObjectInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """
    
    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Returns the name of the class for which 
            we are providing information.
        """
        return 'Event'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "Event"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "event"
        
    #---------------------------------------------------------------#
    
    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """
        
        return ImageFile('skins/Event_icon.gif', globals())

    #---------------------------------------------------------------#

    def isContainer(self):
        """
            Returns if the instance is providing folderish/container
            services.
            
            Override an return true if the instance is to be
            a container for other instances.
            
            NOTE: all instances support "events" so there is no
            need to return true if you require "event" support.
        """

        return true          
        
    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in 
            the specified container (containerInstance)
            
            NOTE: This is from this class' instance perspective.
        """
        
        #Events are only permitted in a Container that;
        # Rule 1. permit the kind of event we are attempting to place in the container
        # Rule 2. don't already have the event defined in the container

        #NOTE: This method is only used by the paste verification
        #as the addition of new events is controlled by the 'Events' tab
        
        #has a containerInstance and event instance been provided?
        if containerInstance != None and instance != None:
            
            #Check Rule 1
            if containerClassInfo.isEventDefined(instance.getIdentity()):
            
                #Check Rule 2
                return containerInstance.getHandledEvent(instance.getIdentity()) == None
            
            else:
                return false
        
        else:
            return false

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a 
            child of the class' instances.
            
            NOTE: This is from this class's instance perspective.
            
            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """
        
        #DEFAULT RULE: Events may only contain Actions
        return childClassInfo.isInstanceOf('Action')
    
    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific properties using the PropertyReflection interface.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """

        #initialise the super-class properties for reflection
        GenericObjectInfo.onConfigureProperties(self)
                
        #hide the identity property
        self.getPropertyDefinition('identity').setIsForPropertyEditor(false)
        self.getPropertyDefinition('identity').setIsForConstructor(false)
        
        #hide the id property
        self.getPropertyDefinition('id').setIsForPropertyEditor(false)
        self.getPropertyDefinition('id').setIsForConstructor(false)

        #hide the title property
        self.getPropertyDefinition('title').setIsForPropertyEditor(false)
        self.getPropertyDefinition('title').setIsForConstructor(false)
        
        #add the 'description' property        
        self.addPropertyDefinition(PropertyDefinition(identity="description", displayName="Description", description="The description of the event", defaultValue="", propertyType=pt_STRING, propertyFormat=pf_TEXT_MULTILINE, propertyStructure=ps_ATOMIC, isWritePermitted=false))        
        
        #add the 'isEnabled' property        
        self.addPropertyDefinition(PropertyDefinition(identity="enabled", displayName="Enabled?", description="Should the event actions be processed", defaultValue=true, propertyType=pt_BOOLEAN, propertyFormat=pf_RADIO + pf_YES_NO, propertyStructure=ps_ATOMIC))        
    
    #---------------------------------------------------------------#

    def onConfigurePermissions(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific permission definitions.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """
        

        #initialise the super-class permissions for reflection
        GenericObjectInfo.onConfigurePermissions(self)

    #---------------------------------------------------------------#

#####################################################################
## Event Class Definition
class Event(GenericObject):
    """
        The base implementation of all Knowledge Engine Events
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = EventInfo()

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the object"        
        
        GenericObject.__init__(self, id, identity)
        
        #perform onAfterInstanciation
        self.onAfterInstanciation()

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object 
            has been loaded into memory.  
            
            This is useful for performing backwards compatibility
        """

        #perform default onAfterInstanciation for the container
        GenericObject.onAfterInstanciation(self)
        
    #---------------------------------------------------------------#

    def alterIdentity(self):
        """
            Generates and changes the identity of the object
            CALLED BY: onAfterClone to ensure that pasted objects
            have different identities
        """
        
        #don't do anything - because Event identities must remain constant
        pass
        
    #---------------------------------------------------------------#
        
    def getDescription(self):
        """
            Returns the Description of the event
        """
        
        return self.description        
        
    #---------------------------------------------------------------#
        
    def setDescription(self, description):
        """
            Sets the Description of the event
        """

        self.description = description
        
    #---------------------------------------------------------------#
        
    def isEnabled(self):
        """
            Returns if the event is enabled
        """
        
        return self.enabled
        
    #---------------------------------------------------------------#
        
    def setIsEnabled(self, enabled):
        """
            Sets if the event is enabled
        """
        
        self.enabled = enabled
        
    #---------------------------------------------------------------#

    def isOrderedContainer(self):
        """
            Return if the children of the object may use ordering.
            
            This is to allow the 'Order' column in the Content
            management tab in Zope            
        """

        return true
    
    #---------------------------------------------------------------#

    def getDefinition(self):
        """
            Return the associated EventDefinition for this event type
        """
        
        return self.getParent().getClassInfo().getEventDefinition(self.getId())
        
    #---------------------------------------------------------------#
    
    def execute(self, assessment, user = None):
        """
            Attempts to execute the action(s) contained for 
            this event on the SERVER, returning true if the action(s) 
            performed some task or false if no tasks where executed.
        """            

        #get the actions for the event (in order)
        actions = self.getChildrenByOrder()
        
        #(assume the last action was successful)
        lLastActionSuccess = true
        for action in actions:
            
            #execute the current action
            lLastActionSuccess = action.execute(assessment, user, lLastActionSuccess)
        
        #return if anything happened
        return true
        
    #---------------------------------------------------------------#
    
#####################################################################
## Class Initialisation

# Register Class Information with the Knowledge Engine
registerGenericObjectClass(Event)

#####################################################################
